package main

import "fmt"
import "image"
import "image/color"
import "image/draw"
import "io/ioutil"

// import "code.google.com/p/x-go-binding/ui"
import "code.google.com/p/x-go-binding/xgb"
import "code.google.com/p/x-go-binding/ui"
import "code.google.com/p/x-go-binding/ui/x11"
import "code.google.com/p/ehedgehog/xtinker/keys"
import "code.google.com/p/ehedgehog/xtinker/buffer"
import "code.google.com/p/jamslam-freetype-go/freetype"
import "code.google.com/p/jamslam-freetype-go/freetype/raster"
import "code.google.com/p/jamslam-freetype-go/freetype/truetype"

func main() {
	w, _ := x11.NewWindowDisplay(":0")

	white := image.NewUniform(color.RGBA{0xdd, 0xdd, 0xdd, 0})
	draw.Draw(w.Screen(), w.Screen().Bounds(), white, image.ZP, draw.Over)

	b := buffer.NewBuffer()
	events := w.EventChan()
	e := &Editing{}
	loc := image.Point{}
	bufferUp(b, e, 'x')
	count := 0
	for event := range events {
		fmt.Println("count", count)
		count += 1
		w.FlushImage()
		switch event := event.(type) {
		case ui.ConfigEvent:
		case ui.MouseEvent:
			_ = loc
			loc = event.Loc
		case ui.KeyEvent:
			key := event.Key
			fmt.Println("key", key)
			bufferUp(b, e, rune(key))
			refresh(w, e, b)
		}
	}
}

type Editing struct {
	Line, Col int32
}

func refresh(w ui.Window, e *Editing, b buffer.Buffer) {
	for i := int32(0); i < b.Size(); i += 1 {
		fmt.Println("line", i, "is", b.Get(i))
		PutString(w, b.Get(i), 0, 0+16*int16(i))
	}
}

func bufferUp(b buffer.Buffer, e *Editing, ch rune) {
	if ch > 0 {
		return
	}
	ch = -ch
	switch ch {
	case keys.XK_Home:

	case keys.XK_End:

	case keys.XK_Up:
		if e.Line > 1 {
			e.Line -= 1
		}

	case keys.XK_Down:

	case keys.XK_Left:
		if e.Col > 0 {
			e.Col -= 1
		}

	case keys.XK_Right:
	case keys.XK_Page_Up:
	case keys.XK_Page_Down:
	case keys.XK_Delete:
	case keys.XK_BackSpace:

	case keys.XK_Return:
		fmt.Println("Return: e.Line =", e.Line)
		b.Split(e.Line, e.Col)
		e.Line += 1
		e.Col = 0

	case 'l' - 'a' + 1:
	case 'j' - 'a' + 1:
	case 'd' - 'a' + 1:
	case keys.XK_F1:

	default:
		if ' ' <= ch && ch <= 126 {
			b.Insert(ch, e.Line, e.Col)
			e.Col += 1
		} else {
			fmt.Println("did not recognise", ch)
			fmt.Println("XK_Up is", keys.XK_Up)
		}
	}
}

func PutString(w ui.Window, message string, x, y int16) {
	image := WriteStringToImage(w, message)
	DisplayImage(w, image, x, y)
}

func ToInt(n raster.Fix32) int {
	return int(n >> 8)
}

var font = loadFont()

func loadFont() *truetype.Font {
	filename := "/usr/share/fonts/liberation/LiberationMono-Regular.ttf"
	fontbytes, err := ioutil.ReadFile(filename)
	panicUnlessNil(err)
	tfont, err := freetype.ParseFont(fontbytes)
	panicUnlessNil(err)
	return tfont
}

func WriteStringToImage(win ui.Window, message string) *image.RGBA {
	font := font

	const FS = 12
	const DPI = 72

	context := freetype.NewContext()
	context.SetFontSize(FS)
	context.SetFont(font)

	BG := image.NewUniform(color.RGBA{0xff, 0xff, 0xff, 0})
	FG := image.NewUniform(color.RGBA{0, 0, 0, 255})

	// BG, FG = FG, BG

	context.SetDPI(DPI)
	context.SetSrc(FG)

	w, h, err := context.MeasureString(message)
	panicUnlessNil(err)
	rgba := image.NewRGBA(image.Rect(0, 0, ToInt(w), ToInt(h)))

	if true {
		draw.Draw(rgba, rgba.Bounds(), BG, image.ZP, draw.Over)
	}
	if false {
		draw.Draw(rgba, rgba.Bounds(), FG, image.ZP, draw.Over)
	}

	context.SetDst(rgba)
	context.SetClip(rgba.Bounds())
	pt, err := context.DrawString(message, raster.Point{0, FS * 256})
	_ = pt
	panicUnlessNil(err)
	// fmt.Println(rgba)
	return rgba
}

func panicUnlessNil(err error) {
	if err != nil {
		panic(err)
	}
}

type Window struct {
	con *xgb.Conn
	win xgb.Id
	gc  xgb.Id
}

func DisplayImage(w ui.Window, rgba *image.RGBA, x, y int16) {

	draw.Draw(w.Screen(),
		w.Screen().Bounds(),
		rgba,
		image.Point{int(x), int(-y)},
		draw.Src)
}
